class Cells {
  constructor(row, col) {
    this.row = row;
    this.col = col;
    this.dom = this._generateCell(row, col);
  }
  _generateCell(row, col) {
    const td = document.createElement('td');
    td.setAttribute('id', `${col}${row}`)
    const div = document.createElement('div');
    div.setAttribute('class', 'cell_text');
    div.style.setProperty('display', 'block');
    div.setAttribute('id', `${col}${row}_text`);
    const inp = document.createElement('input');
    inp.setAttribute('class', 'cell_inp');
    inp.setAttribute('id', `${col}${row}_inp`)
    inp.style.setProperty('display', 'none')
    div.addEventListener('click', () => {
      this._handleCellClick(div, inp)
    })
    inp.addEventListener('blur', () => {
      this._handleInpBlur(div, inp)
    })
    inp.addEventListener('change', (e) => {
      this._handleInpChange(div, inp, e.target.value)
    })
    td.appendChild(div);
    td.appendChild(inp);
    return td
  }
  _handleCellClick(div, inpDom) {
    div.style.setProperty('display', 'none');
    inpDom.style.setProperty('display', 'block');
    inpDom.focus()
  }
  _handleInpBlur(div, inpDom) {
    div.style.setProperty('display', 'block');
    inpDom.style.setProperty('display', 'none');
  }
  _handleInpChange(div, inpDom, val) {
    div.innerText = Cells.evalCell(val)
  }
  static evalCell(exp) {
    if (!exp.startsWith('=')) {
      return exp
    }
    // = A1 + B2 ---> get(0,1) + get(1,2)
    exp = exp
      .slice(1)
      .replace(
        /\b([A-Za-z])(\d{1,2})\b/g,
        (_, c, r) => `get('${c}',${r})`
      )
    try {
      console.log('函数表达式', exp)
      return new Function('get', `return ${exp}`)(Cells.getCellValue)
    } catch (e) {
      console.log('出错', e)
      return `#ERROR ${e}`
    }
  }
  static getCellValue(c, r) {
    const cellVal = document.querySelector(`#${c.toUpperCase()}${r}_inp`).value
    const val = Cells.evalCell(cellVal)
    const num = Number(val)
    return Number.isFinite(num) ? num : val
  }
}
